package chat;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;

/**
 *
 * @author igo
 */
public class Server {
    
    
    private class Cliente extends Thread{
        
        private Socket cSocket;
        private String Nickname = "";
        private ObjectInputStream ois;
        private ObjectOutputStream oos;
        
        public Cliente(Socket cSocket, String nome, ObjectInputStream ois, ObjectOutputStream oos) {
            this.Nickname = nome;
            this.cSocket = cSocket;
            this.ois = ois;
            this.oos = oos;
        }
        
        public Socket getSocket(){
            return cSocket;
        }
        
        public ObjectOutputStream getOut(){
            return oos;
        }
        
        public String getNick(){
            return Nickname;
        }
        
        public void run() {
            //System.out.println("NovoCliente - Inicio Run");
            
            try {                

                Mensagem msg_intro = new Mensagem ("Servidor",Nickname,"Bem-Vindo ao '"+Servidor+"'");
                
                oos.reset();
                oos.writeObject(msg_intro);                
                while (!interrupted()) {

                    Mensagem msg_in = (Mensagem)ois.readObject();
                    
                    //System.out.println("MensagemRecebida: "+msg_in);
                    if(msg_in != null){
                        Nickname = msg_in.getRemetente();
                        ecra.append(msg_in+"\n");
                        
                        // Scroll Down Automatico
                        //if( ((vbar.getValue() + vbar.getVisibleAmount()) == vbar.getMaximum()) )
                            ecra.setCaretPosition( ecra.getDocument().getLength() );
                        // Fim
                        
                        if(msg_in.getMensagem().charAt(0) == '/'){
                            /*Fazer uns poucos comandos
                             * /[nome] Mensagem -> envia uma Mensagem apenas para o [nome]
                            */
                            int x = msg_in.getMensagem().indexOf(" ");
                            
                            try{
                                msg_in.setDestinatario(msg_in.getMensagem().substring(1, x));
                                msg_in.setText(msg_in.getMensagem().substring(x+1));
                                
                                for(int c=0;c<Clientes.size();c++){
                                    Clientes.get(c).getOut().reset();
                                    if(msg_in.getDestinatario().isEmpty())
                                        Clientes.get(c).getOut().writeObject(msg_in);
                                    else if(Clientes.get(c).getNick().equals(msg_in.getDestinatario()) || Clientes.get(c).getNick().equals(msg_in.getRemetente()))
                                        Clientes.get(c).getOut().writeObject(msg_in);
                                }
                            }catch(StringIndexOutOfBoundsException e){
                                
                            }
                            
                        }else{   
                            for(int c=0;c<Clientes.size();c++){
                                Clientes.get(c).getOut().reset();
                                Clientes.get(c).getOut().writeObject(msg_in);
                            }
                        }
                    }else{
                        Clientes.remove(this);
                        Mensagem msgs = new Mensagem(Nickname,"","Desconectou-se!");
                        ecra.append(msgs+"\n");
                        // Scroll Down Automatico
                        //if( ((vbar.getValue() + vbar.getVisibleAmount()) == vbar.getMaximum()) )
                            ecra.setCaretPosition( ecra.getDocument().getLength() );
                        // Fim
                        for(int c=0;c<Clientes.size();c++){
                            Clientes.get(c).getOut().reset();
                            Clientes.get(c).getOut().writeObject(msgs);  
                        }
                        cSocket.close();
                        this.interrupt();
                    }
                } 
            } catch (IOException e) {
                //Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, e);
                Clientes.remove(this);
                Mensagem msgs = new Mensagem(Nickname,"","Desconectou-se!");
                ecra.append(msgs+"\n");
                // Scroll Down Automatico
                if( ((vbar.getValue() + vbar.getVisibleAmount()) == vbar.getMaximum()) )
                    ecra.setCaretPosition( ecra.getDocument().getLength() );
                // Fim
                for(int c=0;c<Clientes.size();c++){
                    try {
                        Clientes.get(c).getOut().writeObject(msgs);
                    } catch (IOException ex) {
                        //Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
                        System.out.println("Lixado!");
                    }
                }
            }catch (ClassNotFoundException ee){
                //Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ee);
                System.out.println("ClassNotFoundException");
            }
        }
    }

    private int port = 24500;
    private JFrame janela = new JFrame("Chat - Servidor V5.0");
    private Container fundo = janela.getContentPane();
    private JTextArea ecra = new JTextArea("");
    private String Servidor = "Servidor do Igo";
    private JScrollBar vbar;
    private JButton fechar = new JButton("Fechar Servidor");
    private LinkedList<Cliente> Clientes = new LinkedList<Cliente>();
    
    public static void main(String[] args) {
        Server C = new Server();
        C.graph();
        C.logic();
    }
    
    private void logic() {
        try {
            
            ServerSocket sSocket = new ServerSocket(port);
            //mostrador.append("// A Aguardar Conexões\n");
            while(true){
                Socket cSocket = sSocket.accept();
                
                ObjectInputStream ois = new ObjectInputStream(cSocket.getInputStream());
                ObjectOutputStream oos = new ObjectOutputStream(cSocket.getOutputStream());
                
                Mensagem login = (Mensagem)ois.readObject();
                
                ecra.append(login+"\n");
                
                if(login != null){
                    //Aceita conexão através do socket
                    Cliente NC = new Cliente(cSocket, login.getRemetente(), ois, oos);
                    Clientes.add(NC);
                    NC.start();
                }
            }

        } catch (IOException ex) {
            //Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex){
            //Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void graph() {
        janela.setLocation(200, 200);
        janela.setSize(300,200);
        
        fundo.setLayout(new BorderLayout());
        
        ecra.setEditable(false);
        ecra.setBackground(Color.WHITE);
        
        ecra.setLineWrap(true);
        ecra.setWrapStyleWord(true);
        
        JScrollPane sp = new JScrollPane(ecra);
        JPanel pm = new JPanel();
        pm.setLayout(new GridLayout(1,2));
        pm.add(sp);
        sp.setBounds(10,60,10,15);
        sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
        
        vbar = sp.getVerticalScrollBar();
        
        fechar.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                try {
                    for(int i=0; i<Clientes.size();i++){
                        Mensagem M = new Mensagem("Servidor",Clientes.get(i).getNick(),"Desligado");
                        Clientes.get(i).getOut().writeObject(M);
                        Clientes.get(i).getSocket().close();
                    }
                } catch (IOException ex) {
                    //Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
                }
                System.exit(0);
            }
        });
        
        fundo.add(pm, BorderLayout.CENTER);
        fundo.add(fechar, BorderLayout.SOUTH);
        
        janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        janela.setVisible(true);
    }
    
    public String getNome(){
        return Servidor;
    }
}